﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ToolKitIESiteList.Library
{
    public static class SiteDiscovery
    {
        public static IEnumerable<DataDiscovery> Sanitize(DataDiscovery[] data, string[] itensToRemove)
        {
            var entries = data.AsEnumerable();
            if (itensToRemove != null)
            {
                entries = entries.Where(e => !itensToRemove.Contains(e.Url.GetHostAndPort()));
            }
            //Seleciona distintamente pelo host e modo de documento
            return entries.Distinct(new DataDiscoveryDocModeHostComparer());
        }


        public static void MakeEMIESiteList(IEnumerable<IEMXmlItem> entries, Stream memStream)
        {
            var siteEntries = entries.Select(entry => new XElement("site",
                                new XAttribute("url", string.Format("{0}{1}", entry.Uri.GetHostAndPort(), entry.Uri.LocalPath)),
                                new XElement("compat-mode", entry.CompatMode),
                                new XElement("open-in", entry.OpenIn)));

            XElement siteList = new XElement("site-list", new XAttribute("version", 0), siteEntries);

            //Salva o arquivo em memorystream
            siteList.Save(memStream);
        }
        public static DataDiscovery[] Load(string[] siteDiscoveryFiles)
        {
            //Carrega os itens
            IEnumerable<DataDiscovery> internalItens = LoadFiles(siteDiscoveryFiles);

            //Obtém as urls distintamente (Distinct)
            return (from entry in internalItens
                                    group entry by new
                                    {
                                        HostPort = entry.Url.GetHostAndPort(),
                                        Scheme = entry.Url.Scheme,
                                        Path = entry.Url.LocalPath.Split('?')[0],
                                        DocMode = entry.DocMode
                                    } into path
                                    select new DataDiscovery()
                                    {
                                        Url = new Uri(string.Format("{0}://{1}{2}", path.Key.Scheme, path.Key.HostPort, path.Key.Path)),
                                        DocMode = path.Key.DocMode,
                                        NumberOfVisits = path.Sum(p => p.NumberOfVisits)
                                    }).ToArray();
        }

        public static IEnumerable<string> ListDomains(DataDiscovery[] entries)
        {
            return from entry in entries
                   group entry by
                        entry.Url.GetHostAndPort()
                   into domain
                   select domain.Key;
        }

        private static IEnumerable<DataDiscovery> LoadFiles(string[] siteDiscoveryFiles)
        {
            var discoveryEntries = new ConcurrentBag<DataDiscovery>();
            //Carrega todos os arquivos
            Parallel.ForEach(siteDiscoveryFiles, item =>
            {
                IEnumerable<DataDiscovery> entries = ReadEnterpriseDiscoveryXml(item);
                if (entries != null)
                {
                    foreach (var entry in entries)
                        discoveryEntries.Add(entry);
                }
            });
            return discoveryEntries.AsEnumerable();
        }

        private static IEnumerable<DataDiscovery> ReadEnterpriseDiscoveryXml(string fileName)
        {
            var discoverListxml = XElement.Load(fileName);

            return discoverListxml.Elements("IEURLInfo").Where(e => e.Elements("DocMode").Any()).Select(e =>
            {
                var url = HelperEmie.CreateValidUri(e.Element("URL").Value);
                return new DataDiscovery()
                {
                    Url = url,
                    NumberOfVisits = Convert.ToInt32(e.Element("NumberOfVisits").Value),
                    DocMode = e.Element("DocMode").Value,
                    DocModeReason = e.Element("DocModeReason").Value,
                    BrowserStateReason = e.Element("BrowserStateReason").Value
                };
            }).Where(e => e.Url != null);
        }
    }
}
